/*
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/


#ifndef ABSTRACT_H_
#define ABSTRACT_H_

#include <iostream>
#include <string>
#include "error.h"


extern void trim(std::string& s);

template <class T>
class AbstractParser
{
public:
	AbstractParser() {}
	friend class AbstractArg;
	virtual ~AbstractParser() {}
	virtual bool Parse(char* str, int offset, T* pval) 
	{
		return false;
	}
	virtual bool Parse(const char* str, int offset, T* pval) 
	{
		return false;
	}
};

class AbstractArg
{
protected:
	AbstractArg(const char* parceStr, const char* desc = NULL, bool m = true  );
	AbstractArg(const char* desc = NULL, bool m = true);
public:
	
	virtual ~AbstractArg();
	virtual void operator = (char* val) {Set(val);}
	virtual void operator = (std::string val) {Set(val);}
	bool Initialized() {return initialized;}
	// pure virtual functions
	virtual void Set(char* val, int offset = 0) = 0;
	virtual void Set(std::string& val) = 0;
	template<class valT> valT Value()= 0;
	// pure virtual functions

	
	virtual int PrintDecs(std::ostream& out = std::cout);
protected:	

	const char* parser;
	const char* description;
	bool optional;
	static size_t requiredCount;
	bool initialized;
	
	
};

class AbstractOption
{
protected:
	AbstractOption(char k, const char* desc, AbstractArg* pArg);
	AbstractOption(char k, const char* verbKey, const char* desc, AbstractArg* pArg);
public:
	virtual ~AbstractOption();

	static bool HasKey(char k) {return (allKeys.find(k) != std::string::npos);} 
	static bool HasOption(char k) {return (allOptions.find(k) != std::string::npos);}
	bool Initialized() {return initialized;}
	
	// pure virtual functions
	virtual bool Parse(char* str) = 0;
	virtual bool Parse(std::string& s) = 0;
	
	virtual int PrintDecs(int& offset, std::ostream& out = std::cout);	
	AbstractArg* GetArg() {return pArg;}
	virtual bool ExpectValue() = 0; 
	char Key() {return key;}
	const char* VerboseKey() {return verboseKey;}
	int VerboseKeyLen();
protected:
 	static std::string allKeys;
	static std::string allOptions;
	char key;
	const char* description;
	const char* verboseKey;
	AbstractArg* pArg;
	bool initialized;
};


#endif /*ABSTRACT_H_*/
